home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / LISTBOX.C < prev    next >
Text File  |  1991-10-02  |  11KB  |  425 lines

  1. /* ------------- listbox.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include "dflat.h"
  8.  
  9. #ifdef INCLUDE_MULTILINE
  10. static int ExtendSelections(WINDOW, int, int);
  11. static void TestExtended(WINDOW, PARAM);
  12. static void ClearAllSelections(WINDOW);
  13. static void SetSelection(WINDOW, int);
  14. static void FlipSelection(WINDOW, int);
  15. static void ClearSelection(WINDOW, int);
  16. #endif
  17. static void near writeselection(WINDOW, int, int, RECT *);
  18. static void near change_selection(WINDOW, int, int);
  19. static int near selection_in_window(WINDOW, int);
  20.  
  21. int ListBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  22. {
  23.     int rtn, sel;
  24.     static int py = -1;
  25.     int my = (int) p2 - GetTop(wnd);
  26.     RECT rc;
  27.  
  28.     if (my >= wnd->wlines-wnd->wtop)
  29.         my = wnd->wlines - wnd->wtop;
  30.  
  31.     switch (msg)    {
  32.         case CREATE_WINDOW:
  33.             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  34.             wnd->selection = -1;
  35.             wnd->AnchorPoint = -1;
  36.             return rtn;
  37. #ifdef INCLUDE_MULTILINE
  38.         case BORDER:
  39.             if (isMultiLine(wnd))    {
  40.                 char ttl[80] = "";
  41.                 WINDOW wnd1 = wnd;
  42.                 char *cp;
  43.                 if (!TestAttribute(wnd1, HASTITLEBAR))    {
  44.                     if ((wnd1 = GetParent(wnd)) == NULLWND)
  45.                         break;
  46.                     if (!TestAttribute(wnd1, HASTITLEBAR))
  47.                         break;
  48.                 }
  49.                 if (wnd1->title)
  50.                     strcpy(ttl, wnd1->title);
  51.                 if ((cp = strstr(ttl, " (Add)")) != NULL)
  52.                     *cp = '\0';
  53.                 if (wnd->AddMode)
  54.                     /* ---- in Add mode ---- */
  55.                     strcat(ttl, " (Add)");
  56.                 InsertTitle(wnd1, ttl);
  57.                 if (wnd != wnd1)
  58.                     SendMessage(wnd1, BORDER, 0, 0);
  59.             }
  60.             break;
  61. #endif
  62.         case ADDTEXT:
  63.             if (wnd->selection == -1)
  64.                 PostMessage(wnd, LB_SETSELECTION, 0, 0);
  65.             if (*(char *)p1 == LISTSELECTOR)
  66.                 wnd->SelectCount++;
  67.             break;
  68.         case CLEARTEXT:
  69.             wnd->selection = -1;
  70.             wnd->AnchorPoint = -1;
  71.             wnd->SelectCount = 0;
  72.             break;
  73.         case SCROLL:
  74.             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  75.             if ((int)p2 == FALSE)
  76.                 writeselection(wnd, wnd->selection, TRUE, NULL);
  77.             return rtn;
  78.         case KEYBOARD:
  79. #ifdef INCLUDE_SYSTEM_MENUS
  80.             if (WindowMoving || WindowSizing)
  81.                 break;
  82. #endif
  83.             switch ((int) p1)    {
  84. #ifdef INCLUDE_MULTILINE
  85.                 case SHIFT_F8:
  86.                     if (isMultiLine(wnd))    {
  87.                         wnd->AddMode ^= TRUE;
  88.                         SendMessage(GetParent(wnd), ADDSTATUS,
  89.                             wnd->AddMode ? ((PARAM) "Add Mode") : 0, 0);
  90.                     }
  91.                     return TRUE;
  92. #endif
  93.                 case UP:
  94. #ifdef INCLUDE_MULTILINE
  95.                     TestExtended(wnd, p2);
  96. #endif
  97.                     if (wnd->selection > 0)    {
  98.                         if (wnd->selection == wnd->wtop)    {
  99.                             writeselection(wnd, wnd->selection, FALSE, NULL);
  100.                             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  101.                             PostMessage(wnd, LB_SELECTION, wnd->selection-1,
  102.                                 isMultiLine(wnd) ? p2 : FALSE);
  103.                         }
  104.                         else    {
  105.                             int newsel = wnd->selection-1;
  106.                             if (wnd->wlines == ClientHeight(wnd))
  107.                                 while (*TextLine(wnd, newsel) == LINE)
  108.                                     --newsel;
  109.                             PostMessage(wnd, LB_SELECTION, newsel,
  110.                                 isMultiLine(wnd) ? p2 : FALSE);
  111.                         }
  112.                     }
  113.                     return TRUE;
  114.                 case DN:
  115. #ifdef INCLUDE_MULTILINE
  116.                     TestExtended(wnd, p2);
  117. #endif
  118.                     if (wnd->selection < wnd->wlines-1)    {
  119.                         if (wnd->selection == wnd->wtop+ClientHeight(wnd)-1)    {
  120.                             writeselection(wnd, wnd->selection, FALSE, NULL);
  121.                             rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  122.                             PostMessage(wnd, LB_SELECTION, wnd->selection+1,
  123.                                 isMultiLine(wnd) ? p2 : FALSE);
  124.                         }
  125.                         else    {
  126.                             int newsel = wnd->selection+1;
  127.                             if (wnd->wlines == ClientHeight(wnd))
  128.                                 while (*TextLine(wnd, newsel) == LINE)
  129.                                     newsel++;
  130.                             PostMessage(wnd, LB_SELECTION, newsel,
  131.                                 isMultiLine(wnd) ? p2 : FALSE);
  132.                         }
  133.                     }
  134.                     return TRUE;
  135.                 case PGUP:
  136.                 case HOME:
  137. #ifdef INCLUDE_MULTILINE
  138.                     TestExtended(wnd, p2);
  139. #endif
  140.                     rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  141.                     PostMessage(wnd, LB_SELECTION, wnd->wtop,
  142.                         isMultiLine(wnd) ? p2 : FALSE);
  143.                     return rtn;
  144.                 case PGDN:
  145.                 case END:
  146. #ifdef INCLUDE_MULTILINE
  147.                     TestExtended(wnd, p2);
  148. #endif
  149.                     rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  150.                     PostMessage(wnd, LB_SELECTION,
  151.                         wnd->wtop+ClientHeight(wnd)-1,
  152.                         isMultiLine(wnd) ? p2 : FALSE);
  153.                     return rtn;
  154. #ifdef INCLUDE_MULTILINE
  155.                 case ' ':
  156.                     if (!isMultiLine(wnd))
  157.                         break;
  158.                     sel = SendMessage(wnd, LB_CURRENTSELECTION, 0, 0);
  159.                     if (sel == -1)
  160.                         break;
  161.                     if (wnd->AddMode)
  162.                         FlipSelection(wnd, sel);
  163.                     else     {
  164.                         ClearAllSelections(wnd);
  165.                         SetSelection(wnd, sel);
  166.                     }
  167.                     if (!((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))
  168.                         wnd->AnchorPoint = sel;
  169.                     if (ItemSelected(wnd, sel))
  170.                         ExtendSelections(wnd, sel, (int) p2);
  171.                     SendMessage(wnd, PAINT, 0, 0);
  172.                     break;
  173. #endif
  174.                 case '\r':
  175.                     if (wnd->selection != -1)    {
  176.                         int sel = wnd->selection;
  177.                         SendMessage(wnd, LB_SELECTION, sel, TRUE);
  178.                         SendMessage(wnd, LB_CHOOSE, sel, 0);
  179.                     }
  180.                     return TRUE;
  181.                 default:    {
  182.                     int sel = wnd->selection+1;
  183.                     while (sel < wnd->wlines)    {
  184.                         char *cp = TextLine(wnd, sel);
  185.                         if (cp == NULL)
  186.                             break;
  187.                         if (isMultiLine(wnd))
  188.                             cp++;
  189.                         if (*cp == '[')
  190.                             cp++;
  191.                         if (tolower(*cp) == (int)p1)    {
  192.                             SendMessage(wnd, LB_SELECTION, sel,
  193.                                 isMultiLine(wnd) ? p2 : FALSE);
  194.                             if (!selection_in_window(wnd, sel))    {
  195.                                 wnd->wtop = sel-ClientHeight(wnd)+1;
  196.                                 SendMessage(wnd, PAINT, 0, 0);
  197.                             }
  198.                             break;
  199.                         }
  200.                         sel++;
  201.                     }
  202.                     break;
  203.                 }
  204.             }
  205.             break;
  206.         case BUTTON_RELEASED:
  207.             if (HSliding || VSliding)
  208.                 break;
  209.             py = -1;
  210.             return TRUE;
  211.         case LEFT_BUTTON:
  212. #ifdef INCLUDE_SYSTEM_MENUS
  213.             if (WindowMoving || WindowSizing)
  214.                 break;
  215. #endif
  216.             if (!InsideRect(p1, p2, ClientRect(wnd)))
  217.                 break;
  218.             if (my != py)    {
  219.                 int sel = wnd->wtop+my-1;
  220. #ifdef INCLUDE_MULTILINE
  221.                 int sh = getshift();
  222.                 if (!(sh & (LEFTSHIFT | RIGHTSHIFT)))    {
  223.                     if (!(sh & CTRLKEY))
  224.                         ClearAllSelections(wnd);
  225.                     wnd->AnchorPoint = sel;
  226.                     SendMessage(wnd, PAINT, 0, 0);
  227.                 }
  228. #endif
  229.                 SendMessage(wnd, LB_SELECTION, sel, TRUE);
  230.                 py = my;
  231.             }
  232.             return TRUE;
  233.         case DOUBLE_CLICK:
  234.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  235. #ifdef INCLUDE_SYSTEM_MENUS
  236.             if (WindowMoving || WindowSizing)
  237.                 break;
  238. #endif
  239.             rc = ClientRect(wnd);
  240.             if (InsideRect(p1, p2, rc))
  241.                 SendMessage(wnd, LB_CHOOSE,
  242.                     wnd->selection, 0);
  243.             return TRUE;
  244.         case LB_CHOOSE:
  245.             SendMessage(GetParent(wnd), msg, p1, p2);
  246.             break;
  247.         case LB_SETSELECTION:
  248.             change_selection(wnd, (int) p1, 0);
  249.             return TRUE;
  250.         case LB_SELECTION:    {
  251.             WINDOW pwnd = GetParent(wnd);
  252.             CLASS class = GetClass(pwnd);
  253.             change_selection(wnd, (int) p1, (int) p2);
  254.             if (class != LISTBOX && DerivedClass(class) != LISTBOX)
  255.                 SendMessage(GetParent(wnd), LB_SELECTION, wnd->selection, 0);
  256.             return TRUE;
  257.         }
  258.         case LB_CURRENTSELECTION:
  259.             return wnd->selection;
  260.         case LB_GETTEXT:
  261.             if ((int)p2 != -1)    {
  262.                 char *cp1 = (char *)p1;
  263.                 char *cp2 = TextLine(wnd, (int)p2);
  264.                 while (cp2 && *cp2 && *cp2 != '\n')
  265.                     *cp1++ = *cp2++;
  266.                 *cp1 = '\0';
  267.             }
  268.             return TRUE;
  269.         case PAINT:
  270.             if (isVisible(wnd))    {
  271.                 rtn = BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  272. #ifdef INCLUDE_MULTILINE
  273.                 if (isMultiLine(wnd))    {
  274.                     int sel = 0;
  275.                     for (sel = 0; sel < wnd->wlines; sel++)    {
  276.                         if (ItemSelected(wnd, sel))
  277.                             writeselection(wnd, sel, TRUE, (RECT *)p1);
  278.                     }
  279.                 }
  280. #endif
  281.                 writeselection(wnd, wnd->selection, TRUE, (RECT *)p1);
  282.                 return rtn;
  283.             }
  284.             break;
  285.         case HORIZSCROLL:
  286.             return TRUE;
  287.         case CLOSE_WINDOW:
  288.             if (isMultiLine(wnd) && wnd->AddMode)    {
  289.                 wnd->AddMode = FALSE;
  290.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  291.             }
  292.             break;
  293.         default:
  294.             break;
  295.     }
  296.     return BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  297. }
  298.  
  299. #ifdef INCLUDE_MULTILINE
  300.  
  301. static void TestExtended(WINDOW wnd, PARAM p2)
  302. {
  303.     if (isMultiLine(wnd) && !wnd->AddMode &&
  304.             !((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))    {
  305.         if (wnd->SelectCount > 1)    {
  306.             ClearAllSelections(wnd);
  307.             SendMessage(wnd, PAINT, 0, 0);
  308.         }
  309.     }
  310. }
  311.  
  312. static void ClearAllSelections(WINDOW wnd)
  313. {
  314.     if (isMultiLine(wnd) && wnd->SelectCount > 0)    {
  315.         int sel;
  316.         for (sel = 0; sel < wnd->wlines; sel++)
  317.             ClearSelection(wnd, sel);
  318.     }
  319. }
  320.  
  321. static void FlipSelection(WINDOW wnd, int sel)
  322. {
  323.     if (isMultiLine(wnd))    {
  324.         if (ItemSelected(wnd, sel))
  325.             ClearSelection(wnd, sel);
  326.         else
  327.             SetSelection(wnd, sel);
  328.     }
  329. }
  330.  
  331. static int ExtendSelections(WINDOW wnd, int sel, int shift)
  332. {    
  333.     if (shift & (LEFTSHIFT | RIGHTSHIFT) &&
  334.                         wnd->AnchorPoint != -1)    {
  335.         int i = sel;
  336.         int j = wnd->AnchorPoint;
  337.         int rtn;
  338.         if (j > i)
  339.             swap(i,j);
  340.         rtn = i - j;
  341.         while (j <= i)
  342.             SetSelection(wnd, j++);
  343.         return rtn;
  344.     }
  345.     return 0;
  346. }
  347.  
  348. static void SetSelection(WINDOW wnd, int sel)
  349. {
  350.     if (isMultiLine(wnd) && !ItemSelected(wnd, sel))    {
  351.         char *lp = TextLine(wnd, sel);
  352.         *lp = LISTSELECTOR;
  353.         wnd->SelectCount++;
  354.     }
  355. }
  356.  
  357. static void ClearSelection(WINDOW wnd, int sel)
  358. {
  359.     if (isMultiLine(wnd) && ItemSelected(wnd, sel))    {
  360.         char *lp = TextLine(wnd, sel);
  361.         *lp = ' ';
  362.         --wnd->SelectCount;
  363.     }
  364. }
  365.  
  366. int ItemSelected(WINDOW wnd, int sel)
  367. {
  368.     if (isMultiLine(wnd) && sel < wnd->wlines)    {
  369.         char *cp = TextLine(wnd, sel);
  370.         return (int)((*cp) & 255) == LISTSELECTOR;
  371.     }
  372.     return FALSE;
  373. }
  374.  
  375. #endif
  376.  
  377. static int near selection_in_window(WINDOW wnd, int sel)
  378. {
  379.     return (wnd->wlines && sel >= wnd->wtop &&
  380.             sel < wnd->wtop+ClientHeight(wnd));
  381. }
  382.  
  383. static void near writeselection(WINDOW wnd, int sel, int reverse, RECT *rc)
  384. {
  385.     if (selection_in_window(wnd, sel))
  386.         WriteTextLine(wnd, rc, sel, reverse);
  387. }
  388.  
  389. static void near change_selection(WINDOW wnd, int sel, int shift)
  390. {
  391.     if (sel != wnd->selection)    {
  392. #ifdef INCLUDE_MULTILINE
  393.         if (isMultiLine(wnd))        {
  394.             int sels;
  395.             if (!wnd->AddMode)
  396.                 ClearAllSelections(wnd);
  397.             sels = ExtendSelections(wnd, sel, shift);
  398.             if (sels > 1)
  399.                 SendMessage(wnd, PAINT, 0, 0);
  400.             if (sels == 0 && !wnd->AddMode)    {
  401.                 ClearSelection(wnd, wnd->selection);
  402.                 SetSelection(wnd, sel);
  403.                 wnd->AnchorPoint = sel;
  404.             }
  405.         }
  406. #endif
  407.         writeselection(wnd, wnd->selection,
  408. #ifdef INCLUDE_MULTILINE
  409.                 isMultiLine(wnd) ?
  410.                 ItemSelected(wnd, wnd->selection) :
  411. #endif
  412.                 FALSE,
  413.                 NULL);
  414.         wnd->selection = sel;
  415.         writeselection(wnd, sel,
  416. #ifdef INCLUDE_MULTILINE
  417.                 (isMultiLine(wnd) && wnd->AddMode) ?
  418.                 !ItemSelected(wnd, sel) :
  419. #endif
  420.                 TRUE,
  421.                 NULL);
  422.         
  423.     }
  424. }
  425.